package com.ksc.storekeeper.client.view.components;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasKeyUpHandlers;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasCaption;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.ksc.storekeeper.client.resources.StoreKeeperResources;
import com.ksc.storekeeper.client.view.validation.ValidatingTextBox;
import com.ksc.storekeeper.client.view.validation.Validation;

public class FormItemTextBox extends Composite implements HasCaption, HasKeyUpHandlers, HasBlurHandlers {

	private static FormItemTextBoxUiBinder uiBinder = GWT.create(FormItemTextBoxUiBinder.class);

	interface FormItemTextBoxUiBinder extends UiBinder<Widget, FormItemTextBox> {
	}

	@UiField
	HTMLPanel panel;
	@UiField
	Label label;
	@UiField
	ValidatingTextBox input;
	@UiField
	InlineHTML error;
	// @UiField
	// SmallImageButton editInput;

	private boolean validation = false;
	private boolean required = false;
	private boolean alpha = false;
	private boolean numeric = false;
	private boolean alphanumeric = false;
	public String title;

	private String regex = "";
	private String errorMessage = "";
	private String placeholder = null;
	private boolean isPlaceHolderVisible = false;
	private boolean isEditable = true;

	private boolean isReadOnly = false;

	public FormItemTextBox() {
		initWidget(uiBinder.createAndBindUi(this));

		input.addFocusHandler(new FocusHandler() {
			@Override
			public void onFocus(FocusEvent event) {
				hidePlaceholder();
			}
		});

		input.addBlurHandler(new BlurHandler() {

			@Override
			public void onBlur(BlurEvent event) {
				showPlaceholder();
			}
		});

	}

	@Override
	public String getCaption() {
		return label.getText();
	}

	@Override
	public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
		return input.addKeyUpHandler(handler);
	}

	/**
	 * Set caption/label for the item
	 */
	@Override
	public void setCaption(String text) {
		label.setText(text);
	}

	/**
	 * Perform Validation for given attribute
	 * 
	 * @return
	 */
	public boolean validate() {
		boolean valid = true;
		if (validation) {
			input.setRequired(required);
			input.setAlpha(alpha);
			input.setNumeric(numeric);
			input.setAlphaNumeric(alphanumeric);
			valid = input.validate().equals(Validation.VALID) && valid;
			error.setText(input.getErrorMessage());
		}
		return valid;
	}

	/**
	 * Perform email validation
	 * 
	 * @return
	 */
	public boolean validateAsEmail() {
		boolean valid = true;
		if (validation) {
			input.setRequired(required);
			valid = input.validateEmail().equals(Validation.VALID) && valid;
			error.setText(input.getErrorMessage());
		}
		return valid;
	}

	/**
	 * Get item value
	 * 
	 * @return
	 */
	public String getText() {
		if (isPlaceHolderVisible) {
			return "";
		} else {
			return input.getText();
		}
	}

	/**
	 * Set value to item
	 * 
	 * @param text
	 */
	public void setText(String text) {
		input.setText(text.trim());

		if (text == null || text.length() == 0) {
			showPlaceholder();
		} else {
			hidePlaceholder(text);
		}
	}

	public String getErrorText() {
		return error.getText().trim();
	}

	public void setErrorText(String text) {
		input.addStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().error());
		error.setText(text.trim());
	}

	/**
	 * Set parameter validate as true or false
	 * 
	 * @param value
	 */
	public void setValidation(boolean value) {
		validation = value;
	}

	/**
	 * Set parameter required as true or false
	 * 
	 * @param value
	 */
	public void setRequired(boolean value) {
		required = value;
	}

	/**
	 * Set parameter alphabetic as true or false
	 * 
	 * @param value
	 */
	public void setAlphabetic(boolean value) {
		alpha = value;
	}

	public void setAlphaNumeric(boolean value) {
		alphanumeric = value;
	}

	/**
	 * Set parameter numeric as true or false
	 * 
	 * @param value
	 */
	public void setNumeric(boolean value) {
		numeric = value;
	}

	/**
	 * Set parameter maxLength value
	 * 
	 * @param value
	 */
	public void setMaximumLength(int length) {
		input.setMaxLength(length);
	}

	/**
	 * Set parameter minLength value
	 * 
	 * @param value
	 */
	public void setMinimumLength(int length) {
		input.setMinLength(length);
	}

	@Override
	public String getTitle() {
		return title;
	}

	@Override
	public void setTitle(String title) {
		this.title = title;
		input.setTitle(title);
	}

	public String getPlaceholder() {
		return placeholder;
	}

	public void setPlaceholder(String value) {
		if (isPlaceHolderVisible && value != null && !value.equals(placeholder)) {
			// clear the text so the new placeholder will be displayed
			input.setText("");
		}

		placeholder = value;
		showPlaceholder();
	}

	private void showPlaceholder() {
		if (input.getText().equals("") && getPlaceholder() != null) {
			input.getElement().setAttribute("placeholder", getPlaceholder());
			input.setText("");
			isPlaceHolderVisible = true;
		}
	}

	private void hidePlaceholder(String newText) {
		if (isPlaceHolderVisible) {
			input.setText(newText);
			input.getElement().removeAttribute("placeholder");
			isPlaceHolderVisible = false;
		}
	}

	private void hidePlaceholder() {
		hidePlaceholder("");
	}

	/**
	 * Set style for form panel and input box
	 * 
	 * @param panelStyle
	 *            : Apply panel style
	 * @param inputStyle
	 *            : Apply input box style
	 */
	public void setStyle(String panelStyle, String inputStyle) {
		panel.setStyleName(panelStyle);
		input.setStyleName(inputStyle);
	}

	public void setNoLabel(String panelStyle, String inputStyle) {
		label.setVisible(false);
		panel.setStyleName(panelStyle);
		input.setStyleName(inputStyle);
	}

	/**
	 * 
	 * @param style
	 */
	public void setPanelStyle(String style) {
		panel.setStyleName(style);
	}

	/**
	 * 
	 * @param style
	 */
	public void setItemStyle(String style) {
		input.setStyleName(style);
	}

	public void setErrorStyle(String style) {
		error.setStyleName(style);
	}

	public void setLabelStyle(String style) {
		label.setStyleName(style);
	}

	public void setErrorStyle() {
		error.setStyleName(StoreKeeperResources.INSTANCE.storeKeeperCss().errorMessage());
	}

	public void removeInvalid() {
		error.setText("");
		input.removeInvalid();
	}

	public void removeLabel() {
		label.removeFromParent();
	}

	public String getRegex() {
		return regex;
	}

	public void setRegex(String regex) {
		this.regex = regex;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

	public boolean isEditable() {
		return isEditable;
	}

	public void setEditable(boolean isEditable) {
		this.isEditable = isEditable;
	}

	public boolean isReadOnly() {
		return isReadOnly;
	}

	public void setReadOnly(boolean isReadOnly) {
		this.isReadOnly = isReadOnly;
		input.setReadOnly(isReadOnly);
	}

	public void clear() {
		error.setText("");
		setText("");
		input.removeInvalid();
	}

	public void validateOnBlur() {
		boolean valid = true;
		if (regex != null && !regex.isEmpty() && validation) {
			input.setRequired(required);
			input.setRegex(regex);
			input.setSpecificErrorMessage(errorMessage);
			valid = input.validateOnBlur().equals(Validation.VALID) && valid;
			error.setText(input.getErrorMessage());
		}
		if (regex == null || regex.isEmpty()) {
			validate();
		}
		if (input.getText().isEmpty() && !required) {
			error.setText("");
			input.removeInvalid();
		}
	}

	@Override
	public HandlerRegistration addBlurHandler(BlurHandler handler) {
		return input.addBlurHandler(handler);
	}
}